import random
import astar
import searchalg

##################################################
# find a route to evade the player
##################################################
class EvadePlayer(searchalg.SearchAlg):
    def __init__(self):
        self.reset()
        self.start_position = [-1, -1]
        self.end_position = [0, 0]
        self.status = 0 # the start state of the FSM
        self.reset_time = 5
        
    def reset(self):
        self.map = []
        self.way = []

    def adjust_ends(self):
        """ turn around if the tanker is blocked """
        # continue to find a turn point, until get one
        while 1 :
            i = random.randint(0, self.length - 1)
            j = random.randint(0, self.height - 1)
            if self.map[i][j] == 0: # have not been occupied
                break
            self.end_position = [i , j]

    def calculate_ends(self, end_position):
        i = 0
        j = 0
        if end_position[0] <= int(self.length/2):
            if end_position[1] <= int(self.height/2): # the topleft area
                i = end_position[0] + int(self.length/2) - 1
                j = end_position[1]
            else: # the topright area
                i = end_position[0]
                j = end_position[1] - int(self.height/2)
        else:
            if end_position[1] <= int(self.height/2): # the bottomleft area
                i = end_position[0]
                j = end_position[1] + int(self.height/2) - 1
            else: # the bottomright area
                i = end_position[0] - int(self.length/2)
                j = end_position[1]
        # adjust the position until it is not occupied
        while 1:
            if self.map[i][j] == 0:
                self.end_position[0] = i
                self.end_position[1] = j
                break
            else:
                i += random.randint(-1, 1)
                j += random.randint(-1, 1)
                if i < 0:
                    i = 0
                if j < 0:
                    j = 0
                if i > self.length - 1:
                    i = self.length -1
                if j > self.height - 1:
                    j = self.height -1

    def search(self, map, start_position, end_position):
        """ init the algorithm, and find a route """
        self.reset()
        self.map = map
        self.length = len(map)
        self.height = len(map[0])
        
        if self.status == 0: # the first state: move the destination
            if self.start_position == start_position: # the tanker is been blocked
                #self.adjust_ends()
                self.status = 1
            else: # calculate a position that is far away from the player
                self.calculate_ends(end_position)
        if self.status == 1: # the 2nd state: avoid block and wobble
            self.reset_time -= 1
            if self.reset_time <= 0 :
                self.reset_time = 5
                self.status = 0
                while 1:
                    temp_turns = []
                    temp_turns.append(random.randint(0, self.length - 1))
                    temp_turns.append(random.randint(0, self.height - 1))
                    if self.map[temp_turns[0]][temp_turns[1]] == 0:
                        break
                search_al = astar.AStar() # A* algorithm
                self.way = search_al.search(self.map, start_position, temp_turns)
                self.start_position = [-1, -1]
                return self.way
            if self.start_position == start_position: # the tanker is been blocked
                self.adjust_ends()
            if start_position == self.end_position: # reach the turn, go to destination
                self.status = 0
                temp_turns = []
                # random move for 1 second
                while 1:
                    temp_turns = []
                    temp_turns.append(random.randint(0, self.length - 1))
                    temp_turns.append(random.randint(0, self.height - 1))
                    if self.map[temp_turns[0]][temp_turns[1]] == 0:
                        break
                search_al = astar.AStar() # A* algorithm
                self.way = search_al.search(self.map, start_position, temp_turns)
                self.start_position = [-1, -1]
                return self.way

        self.start_position = start_position                

        search_al = astar.AStar() # A* algorithm
        self.way = search_al.search(self.map, self.start_position, self.end_position)
        return self.way